package com.ikingtech.framework.sdk.oss.embedded.configuration;

import com.ikingtech.framework.sdk.oss.embedded.core.DefaultFileTemplate;
import com.ikingtech.framework.sdk.oss.embedded.core.FileTemplate;
import com.ikingtech.framework.sdk.oss.embedded.core.amazon.AmazonS3FileTemplate;
import com.ikingtech.framework.sdk.oss.embedded.core.minio.MinioFileTemplate;
import com.ikingtech.framework.sdk.oss.embedded.properties.OssProperties;
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.errors.*;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;

import java.io.IOException;
import java.net.URI;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * @author tie yan
 */
@Configuration
@EnableConfigurationProperties({OssProperties.class})
public class OssConfiguration {

    @Bean
    @ConditionalOnExpression("${iking.framework.oss.enabled:true} && '${iking.framework.oss.storage-type}'.equals('MINIO')")
    public MinioClient minioClient(OssProperties properties) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        MinioClient minioClient = MinioClient.builder()
                .endpoint(properties.getUrl())
                .credentials(properties.getAccessKey(), properties.getSecretKey())
                .build();
        if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(properties.getDefaultBucketName()).build())) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(properties.getDefaultBucketName()).build());
        }
        return minioClient;
    }

    @Bean
    @ConditionalOnExpression("${iking.framework.oss.enabled:true} && '${iking.framework.oss.storage-type}'.equals('AWS_S3')")
    public S3Client amazonS3Client(OssProperties properties) {
        return S3Client.builder()
                .endpointOverride(URI.create(properties.getUrl()))
                .region(Region.of(properties.getRegion()))
                .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(properties.getAccessKey(), properties.getSecretKey())))
                .build();
    }

    @Bean
    @ConditionalOnProperty(prefix = "iking.framework.oss", name = {"enabled"}, havingValue = "false", matchIfMissing = true)
    public FileTemplate defaultFileTemplate() {
        return new DefaultFileTemplate();
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnBean({S3Client.class})
    @ConditionalOnProperty(prefix = "iking.framework.oss", name = {"storage-type"}, havingValue = "AWS_S3", matchIfMissing = true)
    public FileTemplate amazonS3FileTemplate(S3Client client) {
        return new AmazonS3FileTemplate(client);
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnBean({MinioClient.class})
    @ConditionalOnProperty(prefix = "iking.framework.oss", name = {"storage-type"}, havingValue = "MINIO", matchIfMissing = true)
    public FileTemplate minioFileTemplate(MinioClient client) {
        return new MinioFileTemplate(client);
    }
}
